<template>
  <!-- 上方搜索页面 -->
  <el-card>
    <el-form :inline="true" class="form">
      <el-form-item label="职位搜索">
        <el-input placeholder="请输入搜索内容" v-model="search"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          size="default"
          :disabled="search ? false : true"
          @click="handleSearch"
        >
          搜索
        </el-button>
        <el-button type="primary" size="default" @click="handleRefresh">重置</el-button>
      </el-form-item>
    </el-form>
  </el-card>
  <!-- 下方信息展示页面 -->
  <el-card style="margin: 10px 0px">
    <el-button type="primary" size="default" icon="Plus" @click="handleAdd">添加角色</el-button>
    <el-table style="margin: 30px 0px" border :data="AllRole">
      <el-table-column type="index" label="#" align="center"></el-table-column>
      <el-table-column label="id" align="center" prop="id"></el-table-column>
      <el-table-column label="角色名称" align="center" prop="roleName"></el-table-column>
      <el-table-column label="创建时间" align="center" prop="createTime"></el-table-column>
      <el-table-column label="更新时间" align="center" prop="updateTime"></el-table-column>
      <el-table-column label="操作" width="400x" align="center">
        <!-- eslint-disable -->
        <template #="{ row, $index }">
          <el-button type="primary" size="default" icon="User" @click="handlePermission(row)">
            分配权限
          </el-button>
          <el-button type="primary" size="default" icon="Edit" @click="handleUpdate(row)">
            编辑
          </el-button>
          <el-popconfirm :title="`你确定要删除${row.roleName}吗？`" @confirm="handleDelete(row)">
            <template #reference>
              <el-button type="primary" size="default" icon="Delete">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-model:current-page="pageNo"
      v-model:page-size="pageSize"
      :page-sizes="[10, 20, 30, 40]"
      @current-change="getRole"
      @size-change="handleSizeChange"
      :background="true"
      layout="prev, pager, next, jumper,->,total, sizes"
      :total="total"
    />
  </el-card>
  <!-- 添加/更新职位的对话框dialog -->
  <el-dialog v-model="show" :title="curRole.id ? '修改职位' : '添加职位'">
    <!-- 获取表单实例，用于表单校验 -->
    <!-- model rules prop都和表单校验有关 -->
    <el-form ref="refForm" :model="curRole" :rules="rules">
      <!--                             rules里面的标识 -->
      <el-form-item label="角色名称" prop="roleName">
        <el-input placeholder="请填写角色名称" v-model="curRole.roleName"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button type="primary" size="default" @click="show = false">取消</el-button>
      <el-button type="primary" size="default" @click="handleAddOrUpdate">确定</el-button>
    </template>
  </el-dialog>
  <!-- 分配职位权限的drawer -->
  <el-drawer v-model="drawer" direction="rtl">
    <template #header>
      <h4>权限分配</h4>
    </template>
    <template #default>
      <!-- 树形控件 -->
      <!--     数据                                         默认展开所有节点      默认选中-->
      <el-tree
        ref="tree"
        :data="menuArr"
        show-checkbox
        node-key="id"
        default-expand-all
        :default-checked-keys="selectedId"
        :props="defaultProps"
      />
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button type="primary" @click="cancel">取消</el-button>
        <el-button type="primary" @click="confirm">确定</el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
//引入ElMessage组件
import { ElMessage } from 'element-plus'
import { ref, onMounted, nextTick } from 'vue'
//引入ts数据类型
import { Role, Menu } from '@/api/acl/role/type'
//引入接口方法
import {
  reqAddOrUpdateRole,
  reqAllPermission,
  reqAllRoleList,
  reqDeleteRole,
  reqSetPermission,
} from '@/api/acl/role/index'
//引入layoutSettingStore
import useLayOutSettingStore from '@/store/modules/setting'

//当前页数
let pageNo = ref<number>(1)
//每页展示数据个数
let pageSize = ref<number>(10)
//总个数
let total = ref<number>(0)
//记录角色信息
let AllRole = ref<Role[]>([])
//搜索内容
let search = ref<string>('')
//layoutSettingStore
let layoutSettingStore = useLayOutSettingStore()
//dialog的显示与隐藏
let show = ref<boolean>(false)
//记录当前职位信息
let curRole = ref<Role>({
  roleName: '',
})
//添加/修改职位表单的vc实例
let refForm = ref<any>()
//drawer的显示与隐藏
let drawer = ref<boolean>(false)
//记录当前职位的权限信息（所有可选权限和已有权限）
let menuArr = ref<Menu[]>()
//记录已勾选权限的id
let selectedId = ref<number[]>([])
//获取树形控件的组件实例
let tree = ref<any>()

onMounted(() => {
  getRole()
})

const getRole = async (pager = 1) => {
  pageNo.value = pager
  let result = await reqAllRoleList(pageNo.value, pageSize.value, search.value)
  if (result.code === 200) {
    AllRole.value = result.data.roles
    total.value = result.data.total
  } else {
    ElMessage({
      type: 'error',
      message: '获取数据失败',
    })
  }
}
//页面显示数据数改变
const handleSizeChange = () => {
  getRole()
}
//搜索的回调
const handleSearch = () => {
  getRole()
  search.value = ''
}
//刷新的回调
const handleRefresh = () => {
  layoutSettingStore.refresh = !layoutSettingStore.refresh
}
//添加/修改职位
const handleAddOrUpdate = async () => {
  //表单校验
  console.log(refForm)
  await refForm.value.validate()
  let result = await reqAddOrUpdateRole(curRole.value)
  if (result.code === 200) {
    ElMessage({
      type: 'success',
      message: curRole.value.id ? '修改成功' : '添加成功',
    })
    //界面消失
    show.value = !show.value
    //刷新数据
    getRole(curRole.value.id ? pageNo.value : 1)
  } else {
    ElMessage({
      type: 'error',
      message: curRole.value.id ? '修改失败' : '添加失败',
    })
  }
}
//添加职位按钮的回调
const handleAdd = () => {
  //数据清空
  Object.assign(curRole.value, {
    roleName: '',
  })
  show.value = !show.value
  //清除上一次的错误提示
  nextTick(() => {
    refForm.value.clearValidate('roleName')
  })
}
//修改职位按钮的回调
const handleUpdate = (row: Role) => {
  Object.assign(curRole.value, row)
  show.value = !show.value
  //清除上一次的错误提示
  nextTick(() => {
    refForm.value.clearValidate('roleName')
  })
}
//规则函数
//@ts-ignore
const validateRoleName = (rule, value, callBack) => {
  console.log(value)
  if (value.trim().length >= 2) {
    callBack()
  } else {
    callBack(new Error('职位名称至少两位'))
  }
}
//添加/修改职位的表单校验规则
const rules = {
  roleName: [{ required: true, trigger: 'blur', validator: validateRoleName }],
}
//drawer取消按钮的回调
const cancel = () => {
  drawer.value = !drawer.value
}
//drawer确定按钮的回调
const confirm = async () => {
  let arr1 = tree.value.getCheckedKeys()
  let arr2 = tree.value.getHalfCheckedKeys()
  let permissionId = arr1.concat(arr2)
  let result = await reqSetPermission(curRole.value.id, permissionId)
  if (result.code === 200) {
    ElMessage({
      type: 'success',
      message: '分配权限成功',
    })
    //直接刷新网页，因为用户自身的权限可能改变
    window.location.reload()
  } else {
    ElMessage({
      type: 'error',
      message: '分配权限失败',
    })
  }
}
//分配权限按钮的回调
const handlePermission = async (row: Role) => {
  Object.assign(curRole.value, row)
  let result = await reqAllPermission(curRole.value.id)
  if (result.code === 200) {
    menuArr.value = result.data
    drawer.value = !drawer.value
    filterId(menuArr.value)
  } else {
    ElMessage({
      type: 'error',
      message: '获取数据失败',
    })
  }
}
//树形控件相关参数
const defaultProps = {
  //data中label和children的别名
  children: 'children',
  label: 'name',
}
//筛选已勾选选项的id数组
const filterId = (data: Menu[]) => {
  for (let i = 0; i < data.length; i++) {
    const item = data[i]
    if (item.select === true) {
      //如果是四级，则加入数组中
      if (item.level === 4) {
        selectedId.value.push(item.id)
      }
      //递归data的children
      filterId(item.children)
    }
  }
}
//删除职位按钮的回调
const handleDelete = async (row: Role) => {
  let result = await reqDeleteRole(row.id)
  if (result.code === 200) {
    ElMessage({
      type: 'success',
      message: '删除成功',
    })
    getRole()
  } else {
    ElMessage({
      type: 'error',
      message: '删除失败',
    })
  }
}
</script>

<style scoped lang="scss">
.form {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
